package com.fanco.learn_datastruct_leetcode.juc;
/**
 * @author qiaowang 2021/8/11
 */

/**
 * @author fanco
 * @Desc volatile关键字 原子性测试Demo
 * 1. 在 number 字段已经添加了 volatile关键字的情况下，多个线程同时对 它执行加操作，观察最后的结果是否符合期望值
 * 2. 提出解决方案
 *   >  1. 加锁 synchronized （杀鸡用牛刀）
 *   >  2. 原子类  （Atomic）
 *
 * 思考： 为什么volatile无法保证原子性？
 * java中 只有对 基本变量的 赋值和读取 如： i=1这种是原子操作， 其他的比如 i++、j=i这种都不是原子操作，因此无法保证原子性
 * volatile 可以 保证 对这个变量的读取是最新的，但是 涉及到 ++等非原子性操作，这就无法保证原子性了。
 */
public class VolatileAtomicDemo {
    public static void main(String[] args) {
        System.out.println("测试Volatile是否保证原子性");
        MyData myData = new MyData();
        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 线程启动");
                for (int j = 0; j < 1000; j++) {
                    myData.addNumber();

                    myData.atomicAdd();
                }
            }, "线程" + i).start();
        }
        // 保证主线程是在其他线程执行完了 再进行 获取值，否则获取为0
        while (Thread.activeCount() > 2) {
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName() + "非原子性操作 获取MyData的number等于" + myData.number);
        // 得到的值 != 20* 1000
        System.out.println(Thread.currentThread().getName() + " 原子性操作 获取MyData的number等于" + myData.atomicInteger.get());

    }
}
